(in-package :cl-mongo-test)

(defmacro with-test-package (desc &rest args)
  `(handler-case
       (multiple-value-prog1 
	   (prog2
	       (format t "---- starting test of package : { ~A } ---------------~%" ,desc)
	       ,@args
	       (format t "---- finished test of package { ~A } sucessfully ------~%" ,desc)))
       (error (c)
	 (progn
	   (format t "test-package '~A' failed with error : ~% *) ~A ~%" ,desc c)))))

	      
(defmacro run-test (desc expected found)
  `(handler-case
       (multiple-value-prog1 
	   (let ((description ,desc))
	     (assert-eql ,expected ,found description)))
     (error (c)
       (format t "test ~A failed with error ~A ~%" ,desc c))))

(defmacro run-test-equal (desc expected found)
  `(handler-case
       (multiple-value-prog1 
	   (let ((description ,desc))
	     (assert-equal ,expected ,found description)))
     (error (c)
       (format t "test ~A failed with error ~A ~%" ,desc c))))
	      

(defun force-single-float (n)
  (coerce n 'single-float))

(defun force-double-float (n)
  (coerce n 'double-float))

(defun geometric-range* (base length accum factor)
  (if (zerop length)
      (mapcar #'floor (nreverse accum))
      (geometric-range* base (decf length) (cons (* (* factor base) (car accum)) accum) factor)))

(defun geometric-range (base length &optional (factor 1))
  (geometric-range* base (decf length) (list base) factor))

(defun reset-test-collection (collection size &optional (wait 0) )
  (with-mongo-connection (:host "localhost" :port *mongo-default-port* :db "test" )
    (rm collection :all)
    (let ((count (length (docs (iter (db.find collection :all))))))
      (assert-eql t (zerop count))))
  (insert-lots collection size)
  (sleep wait)
  (with-mongo-connection (:host "localhost" :port *mongo-default-port* :db "test" )
    (let ((count (length (docs (iter (db.find collection :all)))))
	  (message (format nil "less documents seen than were inserted; try sleeping !")))
      (assert-eql size  count message))))


(defun send-doc-in-doc-in-doc (collection)
  (with-mongo-connection (:host "localhost" :port *mongo-default-port* :db "test" )
			 (let ((doc (make-document)))
			   (add-element "date-time" (date-time 12 34 16 5 4 2010) doc)
			   (add-element "string" "hello world generated by test-document" doc)
			   (add-element "number89" 89 doc)
			   (add-element "numberbig" 89988787777887 doc)
			   (add-element "float 89.67" 89.67 doc)
			   (add-element "list-1" (list 1 2 3 4) doc)
			   (add-element "list-2" (list 1 (list "inside" 3 4 "list" ) "the end") doc)
			   (let ((doc2 (make-document)))
			     (add-element "key-1" "doc in doc !!" doc2)
			     (add-element "key-2" 56.89 doc2)
			     (let ((doc3 (make-document)))
			       (add-element "array" (list (list (list "inside a nest!!"))) doc3)
			       (add-element "key56" 56 doc3)
			       (add-element "doc3" doc3 doc2)
			       (add-element "doc2" doc2 doc)
			       (db.insert collection doc ))))))


(defun test-doc-simple (collection)
  (with-mongo-connection (:host "localhost" :port *mongo-default-port* :db "test" )
			 (let ((doc (make-document)))
			   (add-element "string" "hello world generated by test-document" doc)
			   (add-element "1" 1 doc)
			   (add-element "2" 2 doc)
			   (add-element "3" 3 doc)
			   (add-element "4" 40 doc)
			   (add-element "5" 30 doc)
			   (db.insert collection doc ))))

(defun send-test-document (collection)
  (with-mongo-connection (:host "localhost" :port *mongo-default-port* :db "test" )
			 (let ((doc (make-document)))
			   (add-element "string" "hello world generated by test-document" doc)
			   (add-element "number89" 89 doc)
			   (add-element "numberbig" 89988787777887 doc)
			   (add-element "float 89.67" 89.67 doc)
			   (add-element "list-1" (list 1 2 3 4) doc)
			   (add-element "list-2" (list 1 (list "inside" 3 4 "list" ) "the end") doc)
			   (db.insert collection doc ))))

(defun insert-lots (collection n &key (host "localhost" ) (port *mongo-default-port*) (db "test"))
  (with-mongo-connection (:host host :port port :db db )
    (dotimes (i n)
      (let ((doc (make-document)))
	(add-element (format  nil "name") "simple" doc)
	(add-element (format nil "~D" i) i doc)
	(add-element (format nil "k") (+ 56.00 i) doc)
	(add-element (format nil "l") (- i 9.00)  doc)
	(add-element (format nil "index-this") i doc)
	(add-element (format nil "index_this2") i doc)
	(add-element (format nil "value-1") (* 78 i) doc)
	(db.insert collection doc )))))

(defun insert-lots-more (collection n &key (host "localhost" ) (port *mongo-default-port*) (db "test"))
  (with-mongo-connection (:host host  :port port :db db)
    (dotimes (i n)
      (let ((doc (make-document)))
	(add-element (format  nil "name") "weird" doc)
	(add-element (format  nil "regex") "the fox jumped over the fence" doc)
	(add-element (format nil "~D" i) i doc)
	(add-element (format nil "counter") (- i 9.00)  doc)
	(add-element "list-1" (list 1 2 3 4) doc)
	(add-element "list-2" (list i (* i 2) (- i 3) (+ i 4)) doc)
	(add-element (format nil "index-field") i doc)
	(add-element (format nil "value-2-float") (* 7.8 i) doc)
	(add-element (format nil "boolean true") t doc)
	(add-element (format nil "boolean false") (not t) doc)
	(db.insert collection doc )))))

(defun insert-doc-with-arrays (collection n &key (host "localhost" ) (port *mongo-default-port*) (db "test"))
  (with-mongo-connection (:host host  :port port :db db)
    (dotimes (i n)
      (let ((doc (make-document)))
	(add-element (format  nil "name") (format nil "array-doc-~D" i) doc)
	(add-element "array-1" (list 1 2 (kv (kv "a" 10) (kv "b" (- 45 (* 2 i))) (kv "c" (* i 9)))) doc)
	(add-element "array-2" (list (list (list "a" "b" "c")) (list (kv "Z" (* i 10)) (kv "GG" i))) doc)
	(db.insert collection doc )))))

  

